use std::ops::{Add, Mul, Range};

struct Canvas {}
impl Canvas {
    pub fn write_at(self:&Self,x: i32, y: i32, c: char) {}
}
trait Visible {
    /// 在给定的画布上渲染此对象
    fn draw(&self, canvas: &mut Canvas);
    /// 如果单击(x, y)时应该选中此对象，就返回true
    fn hit_test(&self, x: i32, y: i32) -> bool;
}

struct Broom {
    height: i32,
    x: i32,
    y: i32,
}
impl Visible for Broom {
    fn draw(&self, canvas: &mut Canvas) {
        for y in self.y - self.height - 1..self.y {
            canvas.write_at(self.x, y, '|');
        }
        canvas.write_at(self.x, self.y, 'M');
    }
    fn hit_test(&self, x: i32, y: i32) -> bool {
        self.x == x && self.y - self.height - 1 <= y && y <= self.y
    }
}

impl Broom {
    /// 供下面的Broom::draw()使用的辅助函数
    fn broomstick_range(&self) -> Range<i32> {
        self.y - self.height - 1..self.y
    }
}

pub struct Sink;
use std::io::{Result, Write};
impl Write for Sink {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        // 声称已成功写入了整个缓冲区
        Ok(buf.len())
    }
    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}
#[test]
fn test_dot() {
    let i = dot(&[1, 3, 3], &[1, 3, 4]);
    println!("{}", i);
    assert_eq!(i, 10);
}
fn dot<N>(v1: &[N], v2: &[N]) -> N
where N: Add<Output=N> + Mul<Output=N> + Default + Copy{
    let mut total = N::default();
    for i in 0..v1.len() {
        total = total + v1[i] * v2[i];
    }
    total
}
